/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.longview.io.common.web;

import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import javax.validation.Validator;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ui.Model;
import org.springframework.validation.BindException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.longview.io.common.beanvalidator.BeanValidators;
import com.longview.io.common.config.Global;
import com.longview.io.common.mapper.JsonMapper;
import com.longview.io.common.utils.DateUtils;
import com.longview.io.modules.sms.entity.SmsInfo;
import com.longview.io.modules.sms.service.SmsInfoService;
import com.longview.io.modules.sys.service.SystemService;

/**
 * 控制器支持类
 * @author ThinkGem
 * @version 2013-3-23
 */
public abstract class BaseController {
	public static final String redirect_URL="wx/personalcenter.html";
	/**
	 * 日志对象
	 */
	protected Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * 管理基础路径
	 */
	@Value("${adminPath}")
	protected String adminPath;
	
	/**
	 * 前端基础路径
	 */
	@Value("${frontPath}")
	protected String frontPath;
	
	/**
	 * 前端URL后缀
	 */
	@Value("${urlSuffix}")
	protected String urlSuffix;
	
	/**
	 * 验证Bean实例对象
	 */
	@Autowired
	protected Validator validator;

	/**
	 * 服务端参数有效性验证
	 * @param object 验证的实体对象
	 * @param groups 验证组
	 * @return 验证成功：返回true；严重失败：将错误信息添加到 message 中
	 */
	protected boolean beanValidator(Model model, Object object, Class<?>... groups) {
		try{
			BeanValidators.validateWithException(validator, object, groups);
		}catch(ConstraintViolationException ex){
			List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
			list.add(0, "数据验证失败：");
			addMessage(model, list.toArray(new String[]{}));
			return false;
		}
		return true;
	}
	
	/**
	 * 服务端参数有效性验证
	 * @param object 验证的实体对象
	 * @param groups 验证组
	 * @return 验证成功：返回true；严重失败：将错误信息添加到 flash message 中
	 */
	protected boolean beanValidator(RedirectAttributes redirectAttributes, Object object, Class<?>... groups) {
		try{
			BeanValidators.validateWithException(validator, object, groups);
		}catch(ConstraintViolationException ex){
			List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
			list.add(0, "数据验证失败：");
			addMessage(redirectAttributes, list.toArray(new String[]{}));
			return false;
		}
		return true;
	}
	
	/**
	 * 服务端参数有效性验证
	 * @param object 验证的实体对象
	 * @param groups 验证组，不传入此参数时，同@Valid注解验证
	 * @return 验证成功：继续执行；验证失败：抛出异常跳转400页面。
	 */
	protected void beanValidator(Object object, Class<?>... groups) {
		BeanValidators.validateWithException(validator, object, groups);
	}
	
	/**
	 * 添加Model消息
	 * @param message
	 */
	protected void addMessage(Model model, String... messages) {
		StringBuilder sb = new StringBuilder();
		for (String message : messages){
			sb.append(message).append(messages.length>1?"<br/>":"");
		}
		model.addAttribute("message", sb.toString());
	}
	
	/**
	 * 添加Flash消息
	 * @param message
	 */
	protected void addMessage(RedirectAttributes redirectAttributes, String... messages) {
		StringBuilder sb = new StringBuilder();
		for (String message : messages){
			sb.append(message).append(messages.length>1?"<br/>":"");
		}
		redirectAttributes.addFlashAttribute("message", sb.toString());
	}
	
	/**
	 * 客户端返回JSON字符串
	 * @param response
	 * @param object
	 * @return
	 */
	protected String renderString(HttpServletResponse response, Object object) {
		return renderString(response, JsonMapper.toJsonString(object), "application/json");
	}
	
	/**
	 * 客户端返回字符串
	 * @param response
	 * @param string
	 * @return
	 */
	protected String renderString(HttpServletResponse response, String string, String type) {
		try {
			response.reset();
	        response.setContentType(type);
	        response.setCharacterEncoding("utf-8");
			response.getWriter().print(string);
			return null;
		} catch (IOException e) {
			return null;
		}
	}

	/**
	 * 参数绑定异常
	 */
	@ExceptionHandler({BindException.class, ConstraintViolationException.class, ValidationException.class})
    public String bindException() {  
        return "error/400";
    }
	
	/**
	 * 授权登录异常
	 */
	@ExceptionHandler({AuthenticationException.class})
    public String authenticationException() {  
        return "error/403";
    }
	
	/**
	 * 初始化数据绑定
	 * 1. 将所有传递进来的String进行HTML编码，防止XSS攻击
	 * 2. 将字段中Date类型转换为String类型
	 */
	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		// String类型转换，将所有传递进来的String进行HTML编码，防止XSS攻击
		binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
			@Override
			public void setAsText(String text) {
				setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
			}
			@Override
			public String getAsText() {
				Object value = getValue();
				return value != null ? value.toString() : "";
			}
		});
		// Date 类型转换
		binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
			@Override
			public void setAsText(String text) {
				setValue(DateUtils.parseDate(text));
			}
//			@Override
//			public String getAsText() {
//				Object value = getValue();
//				return value != null ? DateUtils.formatDateTime((Date)value) : "";
//			}
		});
	}
	protected String getHisSeesionUrl(HttpServletRequest request)
	{
		HttpSession session = request.getSession(true);  
        Object obj = session.getAttribute(SystemService.SESSION_LOGIN_URL);  
        // 判断如果没有取到用户信息，就跳转到登陆页面，提示用户进行登陆  
        if (obj == null || "".equals(obj.toString())) {  
        	return redirect_URL;
        } 
        else
        	return obj.toString();
	}
	/***
	 * 判断是否登录
	 * @param request
	 * @return
	 */
	protected boolean isLogin(HttpServletRequest request)
	{
		HttpSession session = request.getSession(true);  
		Object obj = session.getAttribute(SystemService.SESSION_NAME_LOGIN_RESULT);  
        if (obj == null || "".equals(obj.toString())) {  
        	return false;
        }
        else
        	return true;
	}
	/***
	 * 获得登录用户信息
	 */
/*	protected ZjUser GetZjLoginUser(HttpServletRequest request)
	{
		HttpSession session = request.getSession(true);  
		Object obj = session.getAttribute(SystemService.SESSION_NAME_LOGIN_RESULT);  
        if (obj == null || "".equals(obj.toString())) {  
        	return null;
        }
        ZjUser user = (ZjUser)obj;
        return user;
	}*/
	
	protected void restLoginErrSession(HttpServletRequest request)
	{
		HttpSession session = request.getSession(true);
		session.setAttribute(Global.VCODE_ERROR, null);
	}
	//获得二维码图片
/*	protected String getQrCodeImagePath(ZjUser zjUser,HttpServletRequest request)
	{
		String savePath = Global.USERFILES_BASE_URL + "QrCode" + "/";
		String fileName =  zjUser.getId()+".png";
		String url = request.getRequestURL().toString().replace(request.getServletPath(), "") + Global.getFrontPath()+"/wx/advisor_Invitation.html?mobile="+zjUser.getMobile();

		String filePath = Global.getUserfilesBaseDir() + savePath ;
		//判断文件是否存在，存在那么不生成
		File file=new File(filePath  + fileName);    
		if(file.exists())    
		{ 
			return request.getContextPath() + savePath + fileName;
		}
		FileUtils.createDirectory(FileUtils.path(filePath));
		System.out.println(filePath  + fileName);
		QRCodeUtils.encoderQRCode(url, filePath  + fileName, "png");//执行生成二维码
		return request.getContextPath() + savePath + fileName;
	}*/
	public int cvCodeVerification(String mobile,String vCode,HttpSession session,SmsInfoService smsInfoService)
	{
		SmsInfo smsInfo = new SmsInfo();
		smsInfo.setMobile(mobile);
		smsInfo.setVCode(vCode);
		//判断验证码，如果超出三次界面弹出图形验证码框
		int ret = smsInfoService.updateByMobileAndCode(smsInfo);
		if(ret <= 0)
		{
			if(null == session.getAttribute(Global.VCODE_ERROR))
				session.setAttribute(Global.VCODE_ERROR, 1);
			else
				session.setAttribute(Global.VCODE_ERROR, Integer.parseInt(session.getAttribute(Global.VCODE_ERROR).toString()) + 1);
			if(null != session.getAttribute(Global.VCODE_ERROR)&& Integer.parseInt(session.getAttribute(Global.VCODE_ERROR).toString())>3)
			{
				return 1;
			}			
			return 2;			
		}
		else
			return 0;
	}
}
